package com.mall.user.domain.model;

import com.mall.user.domain.command.CreateUserCommand;
import com.mall.user.domain.exception.UserAlreadyExistsException;
import com.mall.user.domain.service.UserDomainService;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

/**
 * 用户领域模型
 * 包含用户的基本信息和业务行为
 */
@Slf4j
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User {
    private Long id;
    private UserName name;
    private Age age;
    private Email email;

    /**
     * 创建新用户的构造函数（不包含ID）
     * @param name 用户名
     * @param age 年龄
     * @param email 邮箱
     */
    public User(UserName name, Age age, Email email) {
        this.id = null;
        this.name = name;
        this.age = age;
        this.email = email;
    }

    /**
     * 检查用户是否为新用户（未持久化）
     * @return 是否为新用户
     */
    public boolean isNew() {
        return this.id == null;
    }
    
    /**
     * 检查用户信息是否完整
     * @return 是否完整
     */
    public boolean isComplete() {
        return name != null && age != null && email != null;
    }
    
    /**
     * 获取用户的显示名称
     * @return 显示名称
     */
    public String getDisplayName() {
        return name != null ? name.name() : "未知用户";
    }
    
    /**
     * 检查当前用户是否已存在
     * 通过领域服务来判断用户名是否已被使用
     * @param userDomainService 用户领域服务
     * @return 是否已存在
     */
    public boolean checkExistence(UserDomainService userDomainService) {
        if (name == null) {
            return false;
        }
        return userDomainService.checkUserExists(name);
    }
    
    /**
     * 验证用户是否可以被创建
     * 检查用户信息完整性和唯一性
     * @param userDomainService 用户领域服务
     * @return 是否可以创建
     */
    public boolean canBeCreated(UserDomainService userDomainService) {
        // 检查信息完整性
        if (!isComplete()) {
            return false;
        }
        
        // 检查用户是否已存在
        return !checkExistence(userDomainService);
    }
    
    /**
     * 静态工厂方法：创建新用户
     * 集中处理所有创建用户的校验逻辑
     * @param command 创建用户命令
     * @param userDomainService 用户领域服务
     * @return 创建的用户实例
     * @throws IllegalArgumentException 当命令参数无效时
     * @throws UserAlreadyExistsException 当用户已存在时
     */
    public static User createNewUser(CreateUserCommand command, UserDomainService userDomainService) {
        log.info("开始创建用户，用户名: {}", command.name().name());
        
        // 1. 验证命令参数（CreateUserCommand构造函数中已经包含基本验证）
        // 这里不需要额外验证，因为record的构造函数已经处理了
        
        // 2. 创建用户领域对象
        User user = new User(command.name(), command.age(), command.email());
        
        // 3. 检查用户信息完整性
        if (!user.isComplete()) {
            log.warn("用户信息不完整，无法创建: {}", command.name().name());
            throw new IllegalArgumentException("用户信息不完整，无法创建用户");
        }
        
        // 4. 检查用户是否已存在
        if (user.checkExistence(userDomainService)) {
            log.warn("用户已存在，无法创建: {}", command.name().name());
            throw new UserAlreadyExistsException(command.name().name());
        }
        
        log.info("用户校验通过，可以创建: {}", command.name().name());
        return user;
    }
}
